y
<template>
  <div>
    <div
      v-if="!isStart"
      style="padding: 35px 0; text-align: center; font-size: 40px"
    >
      <h2 class="vintage">简单五子棋</h2>
      <van-dropdown-menu>
        <van-dropdown-item v-model="timeoutTurn" :options="difficulty" />
      </van-dropdown-menu>
      <van-dropdown-menu style="margin-top: 10px">
        <van-dropdown-item v-model="selectToken" :options="tokenType" />
      </van-dropdown-menu>
      <van-button type="primary" @click="start" text="开始游戏" />
    </div>
    <div v-if="isStart" style="width: 646px; margin-top: 20px; margin: 0 auto">
      <div style="text-align: center" v-if="token === 2 || token === 1">
        <div>你是{{ token === 1 ? "黑" : "白" }}子，黑子先行</div>
        <h3 v-if="winValue == 2 || winValue == 1">
          <span v-if="winValue == 1">黑</span>
          <span v-if="winValue == 2">白</span>
          <span>子:获胜</span>
        </h3>
        <h3 v-else>
          <span v-if="onself"> 轮到你了 </span>
          <span v-else> 对方思考中 </span>
        </h3>
        <div style="margin-top: 5px">
          <van-button
            :disabled="!oldChess[1] || !oldChess[2] || !onself"
            style="margin-right: 10px"
            type="warning"
            @click="takeBack"
            text="悔棋"
          />
          <van-button
            v-if="winValue == 2 || winValue == 1"
            type="primary"
            @click="start"
            text="再来一局"
          />
        </div>
      </div>

      <div style="padding: 35px 0; text-align: center">
        <div
          class="box"
          style="background-color: burlywood; padding: 17px"
          v-if="token === 2 || token === 1"
        >
          <div class="row" v-for="(item, row) in checkerboard" :key="row">
            <div v-for="(item2, line) in item" :key="line + 99999" class="item">
              <!-- <div>{{ "x:" + row }}</div>
          <div>{{ "y:" + line }}</div> -->
            </div>
          </div>
        </div>
        <div class="box" v-if="token === 2 || token === 1">
          <div
            class="row"
            v-for="(item, row) in dataList"
            :key="row"
            style="height: 34px"
          >
            <div
              v-for="(item2, line) in item"
              :key="line + 99999"
              :class="{
                item2: true,
                black: item2 === 1,
                white: item2 === 2,
                thisItem:
                  (oldChess['1'] &&
                    oldChess['1'].x === line &&
                    oldChess['1'].y === row) ||
                  (oldChess['2'] &&
                    oldChess['2'].x === line &&
                    oldChess['2'].y === row),
              }"
              @click="changeArr(row, line, item2)"
            ></div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { Button, DropdownMenu, DropdownItem } from "vant";
import { Notify } from "vant";
export default {
  name: "App",
  components: {
    [Button.name]: Button,
    [DropdownMenu.name]: DropdownMenu,
    [DropdownItem.name]: DropdownItem,
  },
  data() {
    return {
      token: 0,
      selectToken: 1,
      checkerboard: [],
      dataList: [],
      onself: true,
      winValue: undefined,
      isStart: false,
      id: null,
      timeoutTurn: 1000,
      oldChess: {
        1: null,
        2: null,
      },
      tokenType: [
        { text: "执黑子(先手)", value: 1 },
        { text: "执白子", value: 2 },
      ],
      difficulty: [
        { text: "简单难度", value: 200 },
        { text: "默认难度", value: 1000 },
        { text: "困难难度", value: 2500 },
        { text: "噩梦难度", value: 5000 },
      ],
    };
  },
  created() {
    const id = window.localStorage.getItem("id");
    if (id) {
      this.id = id;
    }
    this.startBeat();
  },
  methods: {
    start() {
      this.oldChess = {
        1: null,
        2: null,
      };
      this.checkerboard = [];
      this.dataList = [];
      for (let y = 0; y < 18; y++) {
        const tr = [];
        for (let x = 0; x < 18; x++) {
          tr.push(0);
        }
        this.checkerboard.push(tr);
      }
      for (let y = 0; y < 19; y++) {
        const tr = [];
        for (let x = 0; x < 19; x++) {
          tr.push(0);
        }
        this.dataList.push(tr);
      }
      this.token = this.selectToken;
      this.$axios
        .post("/api/start", {
          id: this.id,
          timeoutTurn: this.timeoutTurn,
        })
        .then((res) => {
          console.log(res);
          const data = res.data;
          if (data.code === "ok") {
            this.id = data.id;
            window.localStorage.setItem("id", this.id);
            this.isStart = true;
            this.onself = true;
            this.winValue = null;
            if (this.token === 2) {
              this.begin();
            }
          } else {
            Notify({ type: "danger", message: data.message });
          }
        })
        .catch(() => {
          Notify({ type: "danger", message: "访问异常！请刷新重试！" });
        });
    },
    begin() {
      this.$axios
        .post("/api/begin", {
          id: this.id,
        })
        .then((res) => {
          const data = res.data;
          if (data.code === "ok") {
            const value = this.token === 1 ? 2 : 1;
            this.$set(this.dataList[data.y], data.x, value);
            this.onself = true;
          } else {
            Notify({ type: "danger", message: data.message });
          }
        })
        .catch(() => {
          Notify({ type: "danger", message: "访问异常！请刷新重试！" });
        });
    },
    changeArr(row, line, item) {
      console.log(row, line, item);
      let value = this.token;
      if (item === 0 && this.onself && !this.winValue) {
        //轮到自己了
        this.onself = false;
        //改变是否轮到自己的状态
        //把当前棋盘的状态存到data中
        this.$set(this.dataList[row], line, value);
        this.oldChess[value] = {
          y: row,
          x: line,
        };
        if (this.victory(row, line, value)) {
          Notify({ type: "success", message: "您已获胜！" });
          return;
        }
        // 发送post请求  携带row line 和 value
        this.$axios
          .post("/api/turn", {
            id: this.id,
            y: row,
            x: line,
          })
          .then((res) => {
            const data = res.data;
            if (data.code === "ok") {
              row = data.y;
              line = data.x;
              value = this.token === 1 ? 2 : 1;
              this.oldChess[value] = {
                y: data.y,
                x: data.x,
              };
              this.$set(this.dataList[row], line, value);
              if (this.victory(row, line, value)) {
                Notify({ type: "danger", message: "您输了！" });
                return;
              }
              this.onself = true;
            } else {
              Notify({ type: "danger", message: data.message });
            }
          })
          .catch(() => {
            Notify({ type: "danger", message: "访问异常！请刷新重试！" });
          });
      }
    },
    startBeat() {
      this.beatTask = setInterval(() => {
        if (this.id) {
          this.$axios
            .post("/api/beat", {
              id: this.id,
            })
            .then((res) => {
              if (res.data.code !== "ok") {
                this.id = null;
                window.localStorage.removeItem("id");
              }
            })
            .catch(() => {
              this.id = null;
              window.localStorage.removeItem("id");
            });
        }
      }, 10000);
    },
    victory(row, line, value) {
      const items = [
        {
          y1: row - 5,
          x1: line - 5,
          y2: row + 5,
          x2: line + 5,
        },
        {
          y1: row - 5,
          x1: line,
          y2: row + 5,
          x2: line,
        },
        {
          y1: row + 5,
          x1: line - 5,
          y2: row - 5,
          x2: line + 5,
        },
        {
          y1: row,
          x1: line - 5,
          y2: row,
          x2: line + 5,
        },
      ];
      for (const data of items) {
        const arr = this.getAround(data.y1, data.x1, data.y2, data.x2);
        let index = 0;
        for (const item of arr) {
          index = item === value ? index + 1 : 0;
          if (index >= 5) {
            // 胜利
            this.winValue = value;
            return true;
          }
        }
      }
      return false;
    },
    getAround(y1, x1, y2, x2) {
      const arr = [];
      for (let index = 0; index < 11; index++) {
        const y = y1 === y2 ? y1 : y1 > y2 ? y1 - index : y1 + index;
        const x = x1 === x2 ? x1 : x1 > x2 ? x1 - index : x1 + index;
        if (y >= 0 && y <= 18 && x >= 0 && x <= 18) {
          arr.push(this.dataList[y][x]);
        }
      }
      return arr;
    },
    takeBack() {
      if (this.oldChess[1] && this.oldChess[2]) {
        this.onself = false;
        this.$axios
          .post("/api/takeBack", {
            id: this.id,
          })
          .then((res) => {
            const data = res.data;
            if (data.code == "ok") {
              this.onself = true;
              this.$set(
                this.dataList[this.oldChess[1].y],
                this.oldChess[1].x,
                0
              );
              this.$set(
                this.dataList[this.oldChess[2].y],
                this.oldChess[2].x,
                0
              );
              this.oldChess = {
                1: null,
                2: null,
              };
            } else {
              Notify({ type: "danger", message: data.message });
            }
          })
          .catch(() => {
            this.id = null;
            window.localStorage.removeItem("id");
          });
      }
    },
  },
};
</script>
<style lang="scss">
// * {
//   box-sizing: border-box;
//   margin: 0;
//   padding: 0;
// }
.tran {
  transition: transform 0.5s;
  // margin-top: -400px;
}

.item,
.item2 {
  width: 34px;
  height: 34px;
  border-style: solid;
  text-align: center;
  line-height: 15px;
  overflow: hidden;
  box-sizing: border-box;
  border-width: 0.5px;
  div {
    // height: 12.75px;
    font-size: 16px;
    line-height: 27.5px;
    opacity: 0.5;
  }
}
.item2 {
  border-radius: 50%;
  width: 32px;
  height: 32px;
  margin-right: 2px;
  background: greenyellow;
  left: 67.5px;
  opacity: 0;
}
.thisItem {
  border-color: red;
}
.black {
  opacity: 1;
  background: black;
}
.white {
  opacity: 1;
  background: white;
}
.row {
  overflow: hidden;
  display: flex;
}

.box {
  position: absolute;
}
.vintage {
  background: #eee
    url()
    repeat;
  text-shadow: 5px -5px black, 4px -4px white;
  font-weight: bold;
  -webkit-text-fill-color: transparent;
  -webkit-background-clip: text;
  background-clip: text;
}
</style>
